package org.dftproject.lineagelinkage.core.agents;

import java.util.Date;
import java.util.Iterator;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.dftproject.genesis.core.agents.IAgent;
import org.dftproject.genesis.core.collections.Collection;
import org.dftproject.genesis.core.persistence.IMemento;
import org.dftproject.genesis.core.search.ISearchProvider;
import org.dftproject.genesis.core.search.SearchUtils;
import org.dftproject.genesis.data.genealogy.IPerson;
import org.dftproject.lineagelinkage.core.DuplicateManager;
import org.dftproject.lineagelinkage.metric.IPedigreeMetric;
import org.dftproject.lineagelinkage.metric.PedigreeMetric;
import org.dftproject.lineagelinkage.metric.PedigreeScore;
import org.dftproject.lineagelinkage.metric.PedigreeTarget;

public class FindDuplicatesAgent implements IAgent {

	private static final Log log = LogFactory.getLog(FindDuplicatesAgent.class);
	
	public static final String TYPE_ID = "org.dftproject.lineagelinkage.core.findDuplicates";

	private final String id;
	private final Collection collection;
	
	private final Iterator<IPerson> iterator;
	
	private final IPedigreeMetric pedigreeMetric = new PedigreeMetric();

	public FindDuplicatesAgent(Collection collection) {
		this(TYPE_ID + ":" + collection.getId(), collection);
	}
	
	public FindDuplicatesAgent(String id, Collection collection) {
		this.id = id;
		this.collection = collection;
		
		iterator = collection.getDataProvider().getPersons().iterator();
	}

	public String getId() {
		return id;
	}

	public String getType() {
		return TYPE_ID;
	}

	public String getName() {
		return "Find potential duplicate individuals (" + collection.getName() + ")";
	}
	
	public Collection getCollection() {
		return collection;
	}

	public void start() {
	}

	public void stop() {		
	}

	public synchronized Runnable getNextTask() {
		while (iterator.hasNext()) {
			final IPerson person = iterator.next();
			Date lastVisited = FindDuplicatesAgentState.getDefault().getState(id, person);
			if (lastVisited != null)
				continue;
			FindDuplicatesAgentState.getDefault().putState(id, person, new Date());
			
			return new Runnable() {
	
				public void run() {
					DuplicateManager duplicateManager = DuplicateManager.getDefault();
					
					for (ISearchProvider provider: SearchUtils.getSearchProviders()) {
						for (IPerson duplicate : provider.getPotentialDuplicates(person)) {
							PedigreeScore score = pedigreeMetric.comparePedigrees(person, duplicate);
							if (score == null || score.getTarget() != PedigreeTarget.MISMATCH)
								duplicateManager.addPotentialDuplicate(person, duplicate);
						}
					}
				}
				
			};
		}
		
		return null;
	}

	public String getFactoryId() {
		return FindDuplicatesAgentFactory.ID;
	}

	public void saveState(IMemento memento) {
		memento.putString("id", id);
		memento.putString("collectionId", collection.getId());
	}

}
